﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Hang.Blog.DomainPlus.EntityframeworkExtension;
using Hang.Blog.Dtos.Category;
using Hang.Blog.Entities;
using Hang.Blog.Helper;
using Hang.Blog.Inter;
using Hang.Blog.RepositoryInter;

using Mapster;

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Data;
using Volo.Abp.Domain.Repositories;

namespace Hang.Blog.Imp {
    [Route(StringConsts.Api + "menu")]
    public class MenuAppService : BlogAppService, IMenuAppService {
        private readonly IBlogRepository<Menu> _categoryrepository;
        private readonly IBlogRepository<Article> _articleRepository;


        public MenuAppService(IBlogRepository<Menu> categoryrepository, IBlogRepository<Article> articleRepository) {
            _categoryrepository = categoryrepository;
            _articleRepository = articleRepository;
        }


        /// <summary>
        /// 添加或者更新
        /// </summary>
        /// <param name="category"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("addorupdate")]
        public async Task AddOrUpdate(MenuInsertOrUpdateDto category) {
            if (category.Id.HasValue) {
                //更新
                var _cate = await _categoryrepository.FindAsync(c => c.Id == category.Id.Value);
                _cate.MenuName = category.MenuName;
                _cate.ParentId = category.ParenId;
                if (category.ParenId.HasValue) {
                    //如果不为空
                    var parent = await _categoryrepository.FirstOrDefaultAsync(x => x.Id == category.ParenId);
                    if (parent != null) {
                        _cate.FullPath = parent.FullPath + "," + _cate.Id;
                        _cate.FullName = parent.FullName + "," + _cate.FullName;
                        _cate.Depth = parent.Depth + 1;
                    } else {
                        _cate.FullName = _cate.MenuName.ToString();
                        _cate.FullPath = _cate.Id.ToString();
                        _cate.Depth = 0;
                    }
                    await _categoryrepository.UpdateAsync(_cate);
                } else {
                    //如果为空
                    _cate.FullName = _cate.MenuName.ToString();
                    _cate.FullPath = _cate.Id.ToString();
                    await _categoryrepository.UpdateAsync(_cate);
                }
            } else {
                //添加
                var entity = new Menu() {
                    MenuName = category.MenuName,
                    ParentId = category.ParenId,
                    Id = GuidGenerator.Create(),
                    CreatorId = CurrentUser.Id,
                };
                if (entity.ParentId.HasValue) {
                    var parent = await _categoryrepository.FirstOrDefaultAsync(x => x.Id == entity.ParentId);
                    entity.FullName = parent.FullName + "," + entity.MenuName;
                    entity.FullPath = parent.FullPath + "," + entity.Id.ToString();
                    entity.Depth = parent.Depth + 1;
                } else {
                    //var parent = await _categoryrepository.FirstOrDefaultAsync(x => x.Id == category.ParenId);
                    entity.FullName = entity.MenuName;
                    entity.FullPath = entity.Id + "";
                    entity.Depth = 0;
                }
                await _categoryrepository.InsertAsync(entity);

            }
        }
        /// <summary>
        /// 删除菜单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        [Route("delete")]
        [HttpDelete]
        public async Task Delete(Guid id) {
            var existchild = await _categoryrepository.AnyAsync(x => x.ParentId == id);
            if (existchild) {
                throw new BusinessException("存在子目录不能删除");
            } else {
                await _categoryrepository.DeleteAsync(i => i.Id == id);
            }
        }


        /// <summary>
        /// 获取博客详情 根据Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        [HttpGet]
        [Route("{id}")]
        public async Task<MenuDto> Get(Guid id) {
            var menu = await _categoryrepository.FirstOrDefaultAsync(x => x.Id == id);
            if (menu == null) {
                throw new BusinessException("不存在");
            } else {
                var res = menu.Adapt<MenuDto>();
                if (menu.ParentId.HasValue) {
                    var parentMenu = await _categoryrepository.FirstOrDefaultAsync(x => x.Id == menu.ParentId.Value);
                    res.ParentName = parentMenu.MenuName;
                }
                return res;
            }
        }

        [HttpGet]
        [Route("loadfirst")]
        public async Task<IList<MenuDto>> LoadFirst() {
            var dtos = await (await _categoryrepository.GetDbSetAsync()).Where(x => x.ParentId == null).ProjectToType<MenuDto>().ToListAsync();
            return dtos;
        }

        [HttpGet]
        [Route("loadhomecategory")]
        public async Task<IList<MenuDtos>> LoadHomeCategory() {
            var res = (await (from c in (await _categoryrepository.GetQueryableAsync())
                              join a in (await _articleRepository.GetQueryableAsync())
                              on c.Id equals a.CategoryId
                              select new {
                                  c,
                                  a
                              }).ToListAsync()).GroupBy(x => x.c).Select(x => new MenuDtos() {
                                  Id = x.Key.Id,
                                  MenuName = x.Key.MenuName,
                                  Count = x.Count()
                              }).ToList();
            return res;
        }

        /// <summary>
        /// 分页
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("page")]
        public async Task<PagedResultDto<MenuDto>> Page(MenuPageInputDto dto) {
            var resu = await (from c in (await _categoryrepository.GetQueryableAsync()).WhereIf(!dto.MenuName.IsNullOrWhiteSpace(), x => dto.MenuName.Contains(x.MenuName)).ProjectToType<MenuDto>()
                              join p in (await _categoryrepository.GetQueryableAsync()).Where(x => !x.ParentId.HasValue)
                              on c.ParentId equals p.Id into cs
                              from cparentnull in cs.DefaultIfEmpty()
                              select new MenuDto() {
                                  Depth = c.Depth,
                                  MenuName = c.MenuName,
                                  CreationTime = c.CreationTime,
                                  CreatorId = c.CreatorId,
                                  DeletionTime = c.DeletionTime,
                                  ParentId = c.ParentId,
                                  ParentName = cparentnull.MenuName,
                                  Id = c.Id
                              }).OrderByDescending(x => x.CreationTime)
                .Page(dto);
            return resu;
        }
    }
}
